package com.xinqi.modules.prepare.prepare.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.common.security.utils.UserHelp;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.utils.json.JSON;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.modules.prepare.common.dto.UserBaseInfoDO;
import com.xinqi.modules.prepare.common.manager.PrepareCommonManager;
import com.xinqi.modules.prepare.common.service.PrepareAuthService;
import com.xinqi.modules.prepare.folder.manager.PrepareFileFolderManager;
import com.xinqi.modules.prepare.prepare.convert.PrepareOperateLogConvert;
import com.xinqi.modules.prepare.prepare.domain.PrepareOperateLogEntity;
import com.xinqi.modules.prepare.prepare.dto.PrepareOperateLogExtend;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareOperateLogCreateDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareOperateLogDeleteDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareOperateLogQueryDTO;
import com.xinqi.modules.prepare.prepare.dto.req.PrepareOperateLogUpdateDTO;
import com.xinqi.modules.prepare.prepare.dto.rsp.PrepareOperateLogResultDTO;
import com.xinqi.modules.prepare.prepare.enums.PrepareMemberPermissionEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareOperateTypeEnum;
import com.xinqi.modules.prepare.prepare.manager.PrepareOperateLogManager;
import com.xinqi.modules.prepare.prepare.service.PrepareOperateLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.xinqi.common.base.error.CommonErrors.BAD_REQUEST;

/**
 * 备课区操作记录表服务层实现
 *
 * @author: system
 * @date: 2023/03/19
 */
@Validated
@Service("prepareOperateLogService")
@RequiredArgsConstructor
public class PrepareOperateLogServiceImpl implements PrepareOperateLogService {
    private final PrepareOperateLogConvert prepareOperateLogConvert;
    private final PrepareOperateLogManager prepareOperateLogManager;
    private final PrepareFileFolderManager prepareFileFolderManager;
    private final PrepareCommonManager prepareCommonManager;
    private final PrepareAuthService prepareAuthService;

    /**
     * 分页查询 备课区操作记录表数据
     */
    @Override
    @DS("slaver")
    public PageInfo<PrepareOperateLogResultDTO> page(Param pageable, PrepareOperateLogQueryDTO query) {
        IPage<PrepareOperateLogEntity> page = prepareOperateLogManager.page(
            Pages.page(pageable, OrderItem.desc(Pages.ID)),
            wrapper(query));
        return Pages.convert(page, prepareOperateLogConvert::convert);
    }

    /**
     * 查询 备课区操作记录表数据
     */
    @Override
    public List<PrepareOperateLogResultDTO> find(PrepareOperateLogQueryDTO query) {
        return prepareOperateLogManager.list(wrapper(query)).stream()
            .map(prepareOperateLogConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<PrepareOperateLogEntity> wrapper(PrepareOperateLogQueryDTO query) {
        LambdaQueryWrapper<PrepareOperateLogEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(PrepareOperateLogEntity::getId, v));
        Queries.accept(query.getPrepareId(), v -> wrapper.eq(PrepareOperateLogEntity::getPrepareId, v));
        Queries.accept(query.getPrepareType(), v -> wrapper.eq(PrepareOperateLogEntity::getType, v));
        Queries.accept(query.getOperateType(), v -> wrapper.eq(PrepareOperateLogEntity::getOperateType, v));
        Queries.accept(query.getTitle(), v -> wrapper.like(PrepareOperateLogEntity::getTitle, v));
        Queries.accept(query.getOperateSubType(), v -> wrapper.eq(PrepareOperateLogEntity::getOperateSubType, v));
        return wrapper;
    }

    /**
     * 根据id查询 备课区操作记录表数据
     */
    @Override
    public PrepareOperateLogResultDTO findById(Long id) {
        BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(prepareOperateLogManager.findById(id)).map(prepareOperateLogConvert::convert).orElse(null);
    }

    /**
     * 新增 备课区操作记录表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid PrepareOperateLogCreateDTO dto) {
        PrepareOperateLogEntity entity = prepareOperateLogConvert.create(dto);
        prepareOperateLogManager.save(entity);
        return entity.getId();
    }

    /**
     * 根据id修改 备课区操作记录表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid PrepareOperateLogUpdateDTO dto) {
        PrepareOperateLogEntity old = Optional.ofNullable(prepareOperateLogManager.getById(dto.getId()))
            .orElseThrow(() -> BAD_REQUEST.asException("数据不存在"));
        PrepareOperateLogEntity entity = prepareOperateLogConvert.update(dto);
        return prepareOperateLogManager.updateById(entity);
    }

    /**
     * 根据id删除 备课区操作记录表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return prepareOperateLogManager.removeById(id);
    }

    /**
     * 根据id删除 备课区操作记录表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(PrepareOperateLogDeleteDTO dto) {
        BAD_REQUEST.check(Objects.nonNull(dto.getId()), "ID不能为空");
        return prepareOperateLogManager.deleteById(dto.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean restore(Long id) {
        BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        Long userId = UserHelp.userId();
        UserBaseInfoDO user = Optional.ofNullable(prepareCommonManager.findUserById(userId))
            .orElseThrow(() -> BAD_REQUEST.asException("当前用户不存在"));
        // 获取操作记录
        PrepareOperateLogEntity old = Optional.ofNullable(prepareOperateLogManager.getById(id))
            .orElseThrow(() -> BAD_REQUEST.asException("数据不存在"));
        prepareAuthService.check(old.getPrepareId(), userId, PrepareMemberPermissionEnum.还原);
        BAD_REQUEST.check(Objects.equals(old.getOperateType(), PrepareOperateTypeEnum.FILE_DEL), "只能恢复文件");
        BAD_REQUEST.check(Objects.equals(old.getIsRestore(), YesNoEnum.NO.ordinal()), "该文件已还原");
        BAD_REQUEST.check(old.getDeadlineTime().compareTo(LocalDateTime.now()) > 0, "时间已超过30天");
        // 还原文件
        prepareFileFolderManager.restore(old.getTargetId(), old.getPrepareId(), old.getType());
        // 设置还原 操作人
        PrepareOperateLogExtend extend = Optional.ofNullable(old.getExtend())
            .filter(StringUtils::isNotEmpty)
            .map(v -> JSON.parse(v, PrepareOperateLogExtend.class))
            .orElseGet(PrepareOperateLogExtend::new);
        extend.setRestoreUserId(user.getId());
        extend.setRestoreUserName(user.getNickname());
        extend.setRestoreUserAvatar(user.getAvatar());
        // 设置状态
        PrepareOperateLogEntity entity = new PrepareOperateLogEntity();
        entity.setId(id);
        entity.setIsRestore(YesNoEnum.YES.ordinal());
        entity.setExtend(JSON.stringify(extend));
        prepareOperateLogManager.updateById(entity);
        return true;
    }

}
